package commands

import (
	"encoding/json"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/spf13/cobra"
	client "github.com/yourusername/lvm-manager/pkg/client"
)

// StorageCommands returns a command object for storage management
// It does NOT take a client; instead, each subcommand creates its own client using the --api flag.
func StorageCommands() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "storage",
		Short:   "Manage storage pools and volumes",
		Aliases: []string{"store", "st"},
	}

	cmd.AddCommand(
		storagePoolCmd(),
		storageVolumeCmd(),
	)

	return cmd
}

// storagePoolCmd 存储池相关命令
func storagePoolCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "pool",
		Short: "Manage storage pools",
	}

	cmd.AddCommand(
		storagePoolListCmd(),
		storagePoolGetCmd(),
		storagePoolCreateCmd(),
		storagePoolStartCmd(),
		storagePoolStopCmd(),
		storagePoolRefreshCmd(),
		storagePoolDeleteCmd(),
	)

	return cmd
}

// storageVolumeCmd 存储卷相关命令
func storageVolumeCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "volume",
		Short: "Manage storage volumes",
	}

	cmd.AddCommand(
		storageVolumeListCmd(),
		storageVolumeGetCmd(),
		storageVolumeCreateCmd(),
		storageVolumeDeleteCmd(),
	)

	return cmd
}

// storagePoolListCmd 列出所有存储池
func storagePoolListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "list",
		Short:   "List all storage pools",
		Aliases: []string{"ls"},
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			pools, err := apiClient.ListStoragePools()
			if err != nil {
				return fmt.Errorf("failed to list storage pools: %w", err)
			}

			// 表格输出
			w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
			fmt.Fprintln(w, "NAME\tSTATE\tTYPE\tCAPACITY\tALLOCATION\tAVAILABLE\tAUTOSTART\tPERSISTENT")
			fmt.Fprintln(w, "----\t-----\t----\t--------\t----------\t---------\t---------\t----------")

			for _, p := range pools {
				autostart := "no"
				if p.Autostart {
					autostart = "yes"
				}
				persistent := "no"
				if p.Persistent {
					persistent = "yes"
				}

				capacity := p.Capacity / (1024 * 1024 * 1024)     // GB
				allocation := p.Allocation / (1024 * 1024 * 1024) // GB
				available := p.Available / (1024 * 1024 * 1024)   // GB

				fmt.Fprintf(w, "%s\t%s\t%s\t%dGB\t%dGB\t%dGB\t%s\t%s\n",
					p.Name, p.State, p.Type, capacity, allocation, available, autostart, persistent)
			}
			w.Flush()

			fmt.Printf("\nTotal: %d storage pools\n", len(pools))
			return nil
		},
	}

	return cmd
}

// storagePoolGetCmd 获取存储池详情
func storagePoolGetCmd() *cobra.Command {
	var outputJSON bool
	var includeXML bool

	cmd := &cobra.Command{
		Use:   "get <name>",
		Short: "Get storage pool details",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			name := args[0]
			pool, err := apiClient.GetStoragePool(name, includeXML)
			if err != nil {
				return fmt.Errorf("failed to get storage pool: %w", err)
			}

			if outputJSON {
				data, _ := json.MarshalIndent(pool, "", "  ")
				fmt.Println(string(data))
			} else {
				fmt.Printf("Name:        %s\n", pool.Name)
				fmt.Printf("UUID:        %s\n", pool.UUID)
				fmt.Printf("State:       %s\n", pool.State)
				fmt.Printf("Type:        %s\n", pool.Type)
				fmt.Printf("Capacity:    %d GB\n", pool.Capacity/(1024*1024*1024))
				fmt.Printf("Allocation:  %d GB\n", pool.Allocation/(1024*1024*1024))
				fmt.Printf("Available:   %d GB\n", pool.Available/(1024*1024*1024))
				fmt.Printf("Autostart:   %v\n", pool.Autostart)
				fmt.Printf("Persistent:  %v\n", pool.Persistent)

				if includeXML && pool.XMLConfig != "" {
					fmt.Printf("\nXML Configuration:\n%s\n", pool.XMLConfig)
				}
			}
			return nil
		},
	}

	cmd.Flags().BoolVarP(&outputJSON, "json", "j", false, "Output in JSON format")
	cmd.Flags().BoolVarP(&includeXML, "xml", "x", false, "Include XML configuration")
	return cmd
}

// storagePoolCreateCmd 创建存储池
func storagePoolCreateCmd() *cobra.Command {
	var spec client.CreatePoolSpec

	cmd := &cobra.Command{
		Use:   "create",
		Short: "Create a new storage pool",
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			if spec.Name == "" {
				return fmt.Errorf("name is required")
			}
			if spec.Type == "" {
				return fmt.Errorf("type is required")
			}

			pool, err := apiClient.CreateStoragePool(&spec)
			if err != nil {
				return fmt.Errorf("failed to create storage pool: %w", err)
			}

			fmt.Printf("Storage pool '%s' created successfully (UUID: %s)\n", pool.Name, pool.UUID)
			fmt.Printf("State: %s\n", pool.State)
			return nil
		},
	}

	cmd.Flags().StringVar(&spec.Name, "name", "", "Storage pool name (required)")
	cmd.Flags().StringVar(&spec.Type, "type", "", "Storage pool type (dir, disk, fs, logical, etc.) (required)")
	cmd.Flags().StringVar(&spec.TargetPath, "target-path", "", "Target path for dir/fs type")
	cmd.Flags().StringVar(&spec.SourceDevice, "source-device", "", "Source device for disk type")
	cmd.Flags().StringVar(&spec.SourceFormat, "source-format", "", "Source format for disk type")

	// 标记必需的标志
	cmd.MarkFlagRequired("name")
	cmd.MarkFlagRequired("type")

	return cmd
}

// storagePoolStartCmd 启动存储池
func storagePoolStartCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "start <name>",
		Short: "Start a storage pool",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			name := args[0]

			if err := apiClient.StartStoragePool(name); err != nil {
				return fmt.Errorf("failed to start storage pool: %w", err)
			}
			fmt.Printf("Storage pool '%s' started\n", name)
			return nil
		},
	}
}

// storagePoolStopCmd 停止存储池
func storagePoolStopCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "stop <name>",
		Short: "Stop a storage pool",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			name := args[0]

			if err := apiClient.StopStoragePool(name); err != nil {
				return fmt.Errorf("failed to stop storage pool: %w", err)
			}
			fmt.Printf("Storage pool '%s' stopped\n", name)
			return nil
		},
	}
}

// storagePoolRefreshCmd 刷新存储池
func storagePoolRefreshCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "refresh <name>",
		Short: "Refresh a storage pool",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			name := args[0]

			if err := apiClient.RefreshStoragePool(name); err != nil {
				return fmt.Errorf("failed to refresh storage pool: %w", err)
			}
			fmt.Printf("Storage pool '%s' refreshed\n", name)
			return nil
		},
	}
}

// storagePoolDeleteCmd 删除存储池
func storagePoolDeleteCmd() *cobra.Command {
	return &cobra.Command{
		Use:     "delete <name>",
		Short:   "Delete a storage pool",
		Aliases: []string{"rm"},
		Args:    cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			name := args[0]

			if err := apiClient.DeleteStoragePool(name); err != nil {
				return fmt.Errorf("failed to delete storage pool: %w", err)
			}
			fmt.Printf("Storage pool '%s' deleted\n", name)
			return nil
		},
	}
}

// storageVolumeListCmd 列出存储池中的所有存储卷
func storageVolumeListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "list <pool>",
		Short:   "List all volumes in a storage pool",
		Aliases: []string{"ls"},
		Args:    cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			poolName := args[0]
			volumes, err := apiClient.ListStorageVolumes(poolName)
			if err != nil {
				return fmt.Errorf("failed to list storage volumes: %w", err)
			}

			// 表格输出
			w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
			fmt.Fprintln(w, "NAME\tTYPE\tCAPACITY\tALLOCATION\tPATH")
			fmt.Fprintln(w, "----\t----\t--------\t----------\t----")

			for _, v := range volumes {
				capacity := v.Capacity / (1024 * 1024 * 1024)     // GB
				allocation := v.Allocation / (1024 * 1024 * 1024) // GB

				fmt.Fprintf(w, "%s\t%s\t%dGB\t%dGB\t%s\n",
					v.Name, v.Type, capacity, allocation, v.Path)
			}
			w.Flush()

			fmt.Printf("\nTotal: %d storage volumes\n", len(volumes))
			return nil
		},
	}

	return cmd
}

// storageVolumeGetCmd 获取存储卷详情
func storageVolumeGetCmd() *cobra.Command {
	var outputJSON bool
	var includeXML bool

	cmd := &cobra.Command{
		Use:   "get <pool> <name>",
		Short: "Get storage volume details",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			poolName := args[0]
			name := args[1]
			volume, err := apiClient.GetStorageVolume(poolName, name, includeXML)
			if err != nil {
				return fmt.Errorf("failed to get storage volume: %w", err)
			}

			if outputJSON {
				data, _ := json.MarshalIndent(volume, "", "  ")
				fmt.Println(string(data))
			} else {
				fmt.Printf("Name:        %s\n", volume.Name)
				fmt.Printf("Key:         %s\n", volume.Key)
				fmt.Printf("Path:        %s\n", volume.Path)
				fmt.Printf("Type:        %s\n", volume.Type)
				fmt.Printf("Capacity:    %d GB\n", volume.Capacity/(1024*1024*1024))
				fmt.Printf("Allocation:  %d GB\n", volume.Allocation/(1024*1024*1024))
				fmt.Printf("Pool:        %s\n", volume.Pool)

				if includeXML && volume.XMLConfig != "" {
					fmt.Printf("\nXML Configuration:\n%s\n", volume.XMLConfig)
				}
			}
			return nil
		},
	}

	cmd.Flags().BoolVarP(&outputJSON, "json", "j", false, "Output in JSON format")
	cmd.Flags().BoolVarP(&includeXML, "xml", "x", false, "Include XML configuration")
	return cmd
}

// storageVolumeCreateCmd 创建存储卷
func storageVolumeCreateCmd() *cobra.Command {
	var spec client.CreateVolumeSpec

	cmd := &cobra.Command{
		Use:   "create <pool>",
		Short: "Create a new storage volume",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			poolName := args[0]
			if spec.Name == "" {
				return fmt.Errorf("name is required")
			}
			if spec.Capacity == 0 {
				return fmt.Errorf("capacity is required")
			}

			volume, err := apiClient.CreateStorageVolume(poolName, &spec)
			if err != nil {
				return fmt.Errorf("failed to create storage volume: %w", err)
			}

			fmt.Printf("Storage volume '%s' created successfully in pool '%s'\n", volume.Name, poolName)
			fmt.Printf("Path: %s\n", volume.Path)
			return nil
		},
	}

	cmd.Flags().StringVar(&spec.Name, "name", "", "Storage volume name (required)")
	cmd.Flags().Uint64Var(&spec.Capacity, "capacity", 0, "Storage volume capacity in bytes (required)")
	cmd.Flags().Uint64Var(&spec.Allocation, "allocation", 0, "Storage volume allocation in bytes")
	cmd.Flags().StringVar(&spec.Format, "format", "", "Storage volume format (qcow2, raw, etc.)")

	// 标记必需的标志
	cmd.MarkFlagRequired("name")
	cmd.MarkFlagRequired("capacity")

	return cmd
}

// storageVolumeDeleteCmd 删除存储卷
func storageVolumeDeleteCmd() *cobra.Command {
	return &cobra.Command{
		Use:     "delete <pool> <name>",
		Short:   "Delete a storage volume",
		Aliases: []string{"rm"},
		Args:    cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			poolName := args[0]
			name := args[1]

			if err := apiClient.DeleteStorageVolume(poolName, name); err != nil {
				return fmt.Errorf("failed to delete storage volume: %w", err)
			}
			fmt.Printf("Storage volume '%s' in pool '%s' deleted\n", name, poolName)
			return nil
		},
	}
}
